home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
program
/
misc
/
obrn-a_1.lha
/
oberon-a
/
src_upd1.lha
/
source
/
oc
/
OCC.mod
< prev
next >
Wrap
Text File
|
1995-07-13
|
74KB
|
2,549 lines
(*************************************************************************
$RCSfile: OCC.mod $
Description: Code generation
Created by: fjc (Frank Copeland)
$Revision: 5.23 $
$Author: fjc $
$Date: 1995/07/14 00:42:12 $
Copyright © 1990-1993, ETH Zuerich
Copyright © 1993-1995, Frank Copeland
This module forms part of the OC program
See OC.doc for conditions of use and distribution
Log entries are at the end of the file.
*************************************************************************)
<* STANDARD- *> <* MAIN- *>
MODULE OCC;
IMPORT
SYS := SYSTEM, Files, Str := Strings, OCM, OCS, OCT, OCStrings, OCOut;
(* --- Exported declarations ------------------------------------------ *)
CONST
(* Condition codes *)
T * = 0; F * = 1; HI * = 2; LS * = 3; CC * = 4; CS * = 5;
NE * = 6; EQ * = 7; VC * = 8; VS * = 9; PL * = 10; MI * = 11;
GE * = 12; LT * = 13; GT * = 14; LE * = 15;
(* Instruction mnemonics *)
Bcc * = 6000H; DBcc * = 50C8H; Scc * = 50C0H;
ADD * = 0D000H; ADDI * = 0600H; ADDQ * = 5000H; AND * = 0C000H;
ANDI * = 0200H; ASL * = 0E100H; ASR * = 0E000H; BCC * = 6400H;
BCLR * = 0080H; BCS * = 6500H; BEQ * = 6700H; BGE * = 6C00H;
BGT * = 6E00H; BHI * = 6200H; BLE * = 6F00H; BLS * = 6300H;
BLT * = 6D00H; BMI * = 6B00H; BNE * = 6600H; BPL * = 6A00H;
BRA * = 6000H; BSET * = 00C0H; BSR * = 6100H; BTST * = 0000H;
BVC * = 6800H; BVS * = 6900H; CHK * = 4180H; CLR * = 4200H;
CMP * = 0B000H; CMPI * = 0C00H; DBCC * = 54C8H; DBCS * = 55C8H;
DBEQ * = 57C8H; DBF * = 51C8H; DBGE * = 5CC8H; DBGT * = 5EC8H;
DBHI * = 52C8H; DBLE * = 5FC8H; DBLS * = 53C8H; DBLT * = 5DC8H;
DBMI * = 5BC8H; DBNE * = 56C8H; DBPL * = 5AC8H; DBRA * = 50C8H;
DBT * = 50C8H; DBVC * = 58C8H; DBVS * = 59C8H; DIVS * = 081C0H;
EOR * = 0B100H; EORI * = 0A00H; EXG * = 0C140H; EXTW * = 4880H;
EXTL * = 48C0H; JMP * = 4EC0H; JSR * = 4E80H; LEA * = 41C0H;
LINK * = 4E50H; LSL * = 0E108H; LSR * = 0E008H; MOVEQ* = 7000H;
MULS * = 0C1C0H; NEG * = 4400H; NOP * = 4E71H; NOT * = 4600H;
iOR * = 08000H; ORI * = 0000H; PEA * = 4840H; ROL * = 0E118H;
ROR * = 0E018H; RTE * = 4E73H; RTS * = 4E75H; SCS * = 55C0H;
SEQ * = 57C0H; SF * = 51C0H; SGE * = 5CC0H; SGT * = 5EC0H;
SHI * = 52C0H; SLE * = 5FC0H; SLS * = 53C0H; SLT * = 5DC0H;
SMI * = 5BC0H; SNE * = 56C0H; SPL * = 5AC0H; SRA * = 50C0H;
ST * = 50C0H; SVC * = 58C0H; SVS * = 59C0H; SUB * = 9000H;
SUBI * = 0400H; SUBQ * = 5100H; SWAP * = 4840H; TRAP * = 4E40H;
TRAPV* = 4E76H; TST * = 4A00H; UNLK * = 4E58H;
(* Trap numbers *)
OverflowCheck * = -1;
IndexCheck * = 0;
TypeCheck * = 1;
NilCheck * = 2;
CaseCheck * = 3;
ReturnCheck * = 4;
StackCheck * = 5;
RangeCheck * = 6;
(* CPU Registers *)
D0 = 0; D1 = 1; D2 = 2; D3 = 3; D7 = 7;
A0 = 8; A1 = 9; A3 = 11; A4 = 12; A5 = 13;
A6 = 14; A7 = 15; BP = A4 - 8; FP = A5 - 8; SP = A7 - 8;
DataRegs = {D0 .. D7};
AdrRegs = {A0 .. A7};
(* Register masks for SaveRegisters () *)
ScratchRegs * = {D0, D1, A0, A1};
AllRegs * = {D0 .. A3, A6};
(* Procedures in Kernel *)
kHalt * = 0;
kNewRecord * = 1;
kNewArray * = 2;
kNewSysBlk * = 3;
kDispose * = 4;
kInitGC * = 5;
kMove * = 6;
kStackChk * = 7;
kMul32 * = 8;
kDiv32 * = 9;
kSPFix * = 10;
kSPFlt * = 11;
kSPCmp * = 12;
kSPTst * = 13;
kSPNeg * = 14;
kSPAdd * = 15;
kSPSub * = 16;
kSPMul * = 17;
kSPDiv * = 18;
kSPAbs * = 19;
kInit * = 20;
kEnd * = 21;
kRegisterModule * = 22;
kRegisterType * = 23;
kRegisterCommand * = 24;
numKProcs = 25;
TYPE
RegState *= RECORD
regs *: SET;
obj : ARRAY 16 OF OCT.Object;
count : ARRAY 16 OF SHORTINT;
END; (* RegState *)
VAR
pc * : LONGINT;
level * : INTEGER;
wasderef * : OCT.Object;
regState * : RegState;
genCode * : BOOLEAN;
(* --- Local declarations ----------------------------------------------- *)
CONST
(* MaxBufferSize = 32766; *)
(* MaxCodeLength = MaxBufferSize DIV SIZE (INTEGER); *)
(* MaxConstLength = MaxBufferSize DIV SIZE (CHAR); *)
NumTypes = 64;
(* Object file hunk types *)
hunkUnit = 999; hunkName = 1000; hunkCode = 1001;
hunkData = 1002; hunkBSS = 1003; hunkReloc32 = 1004;
hunkReloc16 = 1005; hunkReloc8 = 1006; hunkExt = 1007;
hunkSymbol = 1008; hunkDebug = 1009; hunkEnd = 1010;
hunkHeader = 1011; hunkOverlay = 1013; hunkBreak = 1014;
hunkDRel32 = 1015; hunkDRel16 = 1016; hunkDRel8 = 1017;
hunkLib = 1018; hunkIndex = 1019; hunkReloc32Short = 1020;
hunkRelReloc32 = 1021; hunkAbsReloc16 = 1022;
hunkAdvisory = 29; hunkChip = 30; hunkFast = 31;
(* Hunk names *)
hunkSmallCode = "SMALLCODE";
hunkSmallData = "SMALLDATA";
hunkMerged = "__MERGED";
(* External symbol types *)
extSymb = 0; extDef = 1; extAbs = 2;
extRes = 3; extRef32 = 129; extCommon = 130;
extRef16 = 131; extRef8 = 132; extDExt32 = 133;
extDExt16 = 134; extDExt8 = 135; extRelRef32 = 136;
extRelCommon = 137; extAbsRef16 = 138; extAbsRef8 = 139;
(* Addressing mode flag values *)
DReg = 0; (* Data Register *)
ARDir = 1; (* Address Register Direct *)
ARInd = 2; (* Address Register Indirect *)
ARPost = 3; (* Address Register with Post-Increment *)
ARPre = 4; (* Address Register with Pre-Decrement *)
ARDisp = 5; (* Address Register with Displacement *)
ARDisX = 6; (* Address Register with Disp. & Index *)
Mode7 = 7;
AbsW = 0; (* Absolute Short (16-bit Address) *)
AbsL = 1; (* Absolute Long (32-bit Address) *)
PCDisX = 3; (* Program Counter Relative, with Disp. & Index *)
Imm = 4; (* Immediate *)
PCDisp = 5; (* Program Counter Relative, with Displacement *)
B = 1; W = 2; L = 4; (* Size types *)
(* object modes *)
Var = OCM.Var; VarX = OCM.VarX; Ind = OCM.Ind; IndX = OCM.IndX;
RegI = OCM.RegI; RegX = OCM.RegX; Lab = OCM.Lab; LabI = OCM.LabI;
Abs = OCM.Abs; Con = OCM.Con; Push = OCM.Push; Pop = OCM.Pop;
Coc = OCM.Coc; Reg = OCM.Reg; Fld = OCM.Fld; Typ = OCM.Typ;
LProc = OCM.LProc; XProc = OCM.XProc; SProc = OCM.SProc;
LibCall = OCM.LibCall; TProc = OCM.TProc; Mod = OCM.Mod;
Head = OCM.Head; RList = OCM.RList; M2Proc = OCM.M2Proc;
CProc = OCM.CProc; AProc = OCM.AProc; VarR = OCM.VarR; IndR = OCM.IndR;
CallBack = OCM.CallBack;
(* structure forms *)
Undef = OCT.Undef; Pointer = OCT.Pointer; Array = OCT.Array;
Record = OCT.Record; ProcTyp = OCT.ProcTyp; PtrTyp = OCT.PtrTyp;
(* System flags *)
OberonFlag = OCM.OberonFlag; M2Flag = OCM.M2Flag; CFlag = OCM.CFlag;
AsmFlag = OCM.AsmFlag;
TYPE
CodeHunk = POINTER TO CodeHunkDesc;
Def = POINTER TO DefDesc;
Ref = POINTER TO RefDesc;
Offset = POINTER TO OffsetDesc;
CodeHunkDesc = RECORD
next : CodeHunk;
start,
length : LONGINT;
defs : Def;
refs : Ref;
END; (* CodeHunkDesc *)
DefDesc = RECORD
next : Def;
object : OCT.Object;
offset : LONGINT;
END; (* DefDesc *)
RefDesc = RECORD
next : Ref;
type : INTEGER;
label : OCT.Label;
count : LONGINT;
offsets : Offset;
END; (* RefDesc *)
OffsetDesc = RECORD
next : Offset;
n : LONGINT;
END; (* OffsetDesc *)
VAR
(* Labels in Module Kernel *)
kernelLab : ARRAY numKProcs OF OCT.Label;
i : INTEGER;
FirstCodeHunk, CurrCodeHunk, InitCodeHunk, Prologue : CodeHunk;
codex, conx : LONGINT;
typex : INTEGER;
CodeLength, ConstLength : LONGINT;
code : POINTER TO ARRAY OF INTEGER;
constant : POINTER TO ARRAY OF CHAR;
type : ARRAY NumTypes OF OCT.Struct;
dataCount, numPtrs : LONGINT;
TYPE
Arg = RECORD
form : INTEGER;
data : LONGINT;
label : OCT.Label;
END; (* Arg *)
CONST
(* Arg forms *)
none = 0; word = 1; long = 2;
(* Ref types *)
wordRef = 3; longRef = 4; smallRef = 5;
(* --- Procedure declarations ------------------------------------------- *)
(*------------------------------------*)
PROCEDURE OpenBuffers* ( codeSize, constSize : LONGINT );
BEGIN (* OpenBuffers *)
CodeLength := codeSize DIV 2; ConstLength := constSize;
IF (CodeLength > 0) & (ConstLength > 0) THEN
NEW (code, CodeLength); NEW (constant, ConstLength);
IF (code # NIL) & (constant # NIL) THEN RETURN END
END;
OCOut.Str0 (OCStrings.OCC1);
HALT (20)
END OpenBuffers;
(*------------------------------------*)
PROCEDURE Init * ();
VAR r : INTEGER;
BEGIN (* Init *)
pc := 0; level := 0; conx := 0; codex := 0; typex := 0;
regState.regs := {}; genCode := TRUE;
FOR r := 0 TO 15 DO regState.obj[r] := NIL; regState.count[r] := 0 END;
OCT.ModuleInit ("Kernel", kernelLab [kInit]);
END Init;
(*------------------------------------*)
PROCEDURE Close * ();
VAR i : INTEGER;
BEGIN (* Close *)
FirstCodeHunk := NIL; CurrCodeHunk := NIL; InitCodeHunk := NIL;
Prologue := NIL;
i := 0; WHILE i < NumTypes DO type [i] := NIL; INC (i) END
END Close;
(*------------------------------------*)
PROCEDURE StartModule* (name : ARRAY OF CHAR);
VAR i : INTEGER; ch : CHAR;
<*$CopyArrays-*>
BEGIN (* StartModule *)
i := 0;
REPEAT
IF conx >= ConstLength THEN OCS.Mark (230); conx := 0 END;
<*$ < NilChk- IndexChk- *>
ch := name [i]; constant [conx] := ch;
<*$ > *>
INC (i); INC (conx)
UNTIL ch = 0X;
END StartModule;
(*------------------------------------*)
PROCEDURE StartPrologue * ();
VAR codeHunk : CodeHunk;
BEGIN (* StartPrologue *)
NEW (codeHunk);
FirstCodeHunk := codeHunk; CurrCodeHunk := codeHunk;
codeHunk.next := NIL; codeHunk.start := codex; codeHunk.length := 0;
codeHunk.defs := NIL; codeHunk.refs := NIL;
Prologue := codeHunk
END StartPrologue;
(*------------------------------------*)
PROCEDURE StartCodeHunk * (initProc : BOOLEAN);
VAR codeHunk : CodeHunk;
BEGIN (* StartCodeHunk *)
NEW (codeHunk);
IF FirstCodeHunk = NIL THEN
FirstCodeHunk := codeHunk; CurrCodeHunk := codeHunk
ELSE
CurrCodeHunk.next := codeHunk; CurrCodeHunk := codeHunk;
END; (* ELSE *)
codeHunk.next := NIL; codeHunk.start := codex; codeHunk.length := 0;
codeHunk.defs := NIL; codeHunk.refs := NIL;
IF initProc THEN InitCodeHunk := codeHunk END;
END StartCodeHunk;
(*------------------------------------*)
PROCEDURE StartProcedure * (proc : OCT.Object);
VAR def : Def;
BEGIN (* StartProcedure *)
NEW (def);
def.next := CurrCodeHunk.defs; CurrCodeHunk.defs := def;
def.object := proc; def.offset := pc - (CurrCodeHunk.start * 2);
END StartProcedure;
(*------------------------------------*)
PROCEDURE EndCodeHunk * ();
BEGIN (* EndCodeHunk *)
CurrCodeHunk.length := codex - CurrCodeHunk.start;
END EndCodeHunk;
(*------------------------------------*)
PROCEDURE AllocString *
(VAR s : ARRAY OF CHAR; len : LONGINT; VAR x : OCT.Item);
VAR i : LONGINT;
BEGIN (* AllocString *)
IF len = 0 THEN
x.lev := 0; x.a0 := -1; x.a1 := 1; x.a2 := 0; x.label := NIL
ELSIF len = 1 THEN
x.lev := 0; x.a0 := -1; x.a1 := 2; x.a2 := ORD (s [0]); x.label := NIL
ELSE
i := 0;
IF (conx + len) >= ConstLength THEN OCS.Mark (230); conx := 0 END;
REPEAT
<*$ < NilChk- IndexChk- *>
constant [conx] := s [i];
<*$ > *>
INC (i); INC (conx)
UNTIL i = len + 1;
x.lev := 0; x.a0 := conx - i; x.a1 := i; x.a2 := 0;
x.label := OCT.ConstLabel
END;
x.obj := NIL
END AllocString;
(*------------------------------------*)
PROCEDURE AllocStringFromChar * (VAR x : OCT.Item);
BEGIN (* AllocStringFromChar *)
IF x.a1 > 2 THEN OCS.Mark (212)
ELSIF x.a0 < 0 THEN
IF x.a1 = 1 THEN
IF conx = 0 THEN
<*$ < NilChk- IndexChk- *>
constant [0] := 0X;
<*$ > *>
conx := 1
END;
x.a0 := conx - 1; x.label := OCT.ConstLabel
ELSIF x.a1 = 2 THEN
IF conx >= ConstLength - 1 THEN OCS.Mark (230); conx := 0 END;
<*$ < NilChk- IndexChk- *>
x.a0 := conx; constant [conx] := CHR (x.a2); INC (conx);
constant [conx] := 0X; INC (conx); x.label := OCT.ConstLabel
<*$ > *>
END;
IF x.obj # NIL THEN x.obj.a0 := x.a0; x.obj.label := x.label END
END
END AllocStringFromChar;
(*------------------------------------*)
PROCEDURE ConcatString *
(VAR s : ARRAY OF CHAR; len : LONGINT; VAR x : OCT.Item);
VAR i, newLen : LONGINT;
BEGIN (* ConcatString *)
IF len > 0 THEN
newLen := len + x.a1 - 1;
IF len + x.a1 = 2 THEN
x.a1 := 2; x.a2 := ORD (s [0])
ELSIF x.a1 = 1 THEN
AllocString (s, len, x)
ELSE
IF x.a1 = 2 THEN AllocStringFromChar (x) END;
i := 0; DEC (conx);
IF (conx + len) >= ConstLength THEN OCS.Mark (230); conx := 0 END;
REPEAT
<*$ < NilChk- IndexChk- *>
constant [conx] := s [i]; INC (i); INC (conx)
<*$ > *>
UNTIL i = len + 1;
INC (x.a1, len)
END
END
END ConcatString;
(*------------------------------------*)
PROCEDURE AllocTypDesc * (typ : OCT.Struct);
VAR t : INTEGER;
BEGIN (* AllocTypDesc *)
IF typ.form = Pointer THEN
t := 0;
WHILE t < typex DO
IF (type [t].form = Pointer) & (type [t].size = typ.size) THEN
typ.adr := t; typ.mno := 0; typ.label := type [t].label;
RETURN
END;
INC (t)
END
END;
IF typex >= NumTypes THEN OCS.Mark (233); typex := 0 END;
type [typex] := typ; typ.adr := typex; INC (typex);
typ.mno := 0; OCT.MakeTypeLabel (typ)
END AllocTypDesc;
(*------------------------------------*)
PROCEDURE GetDReg * (VAR x : OCT.Item; obj : OCT.Object);
VAR r, reg : INTEGER;
BEGIN (* GetDReg *)
IF obj = wasderef THEN obj := NIL END;
x.mode := Reg; x.obj := NIL; x.a0 := D0;
reg := -1;
(*
IF obj # NIL THEN
r := D7;
LOOP
IF regState.obj[r] = obj THEN reg := r; EXIT END;
DEC (r); IF r < D3 THEN EXIT END;
END
END;
IF reg < 0 THEN
r := D7;
LOOP
IF ~(r IN regState.regs) & (regState.obj[r] = NIL) THEN
reg := r; EXIT
END;
DEC (r); IF r < D3 THEN EXIT END;
END
END;
*)
IF reg < 0 THEN
r := D7;
LOOP
IF ~(r IN regState.regs) THEN reg := r; EXIT END;
DEC (r); IF r < D3 THEN EXIT END;
END
END;
IF reg < 0 THEN
OCS.Mark (215)
ELSE
x.a0 := reg; INCL (regState.regs, reg); (*regState.obj[reg] := obj;*)
INC (regState.count[reg])
END
END GetDReg;
(*------------------------------------*)
PROCEDURE GetAReg * (VAR x : OCT.Item; obj : OCT.Object);
VAR r, reg : INTEGER;
BEGIN (* GetAReg *)
IF obj = wasderef THEN obj := NIL END;
x.mode := Reg; x.obj := NIL; x.a0 := A5;
reg := -1;
IF obj # NIL THEN
r := A6;
LOOP
IF regState.obj[r] = obj THEN reg := r; EXIT END;
DEC (r); IF r < A0 THEN EXIT END;
END
END;
IF reg < 0 THEN
r := A3;
LOOP
IF ~(r IN regState.regs) & (regState.obj[r] = NIL) THEN
reg := r; EXIT
END;
DEC (r); IF r < A0 THEN EXIT END;
END;
END;
IF reg < 0 THEN
IF ~(A6 IN regState.regs) & (regState.obj[A6] = NIL) THEN
reg := A6;
END;
END;
IF reg < 0 THEN
r := A3;
LOOP
IF ~(r IN regState.regs) THEN reg := r; EXIT END;
DEC (r); IF r < A0 THEN EXIT END;
END;
END;
IF reg < 0 THEN
IF ~(A6 IN regState.regs) THEN reg := A6 END;
END;
IF reg < 0 THEN
OCS.Mark (215)
ELSE
x.a0 := reg; INCL (regState.regs, reg); regState.obj[reg] := obj;
INC (regState.count[reg])
END;
END GetAReg;
(*------------------------------------*)
PROCEDURE GetAnyReg * (VAR x : OCT.Item; obj : OCT.Object);
VAR r, reg : INTEGER;
BEGIN (* GetAnyReg *)
IF obj = wasderef THEN obj := NIL END;
x.mode := Reg; x.obj := NIL; x.a0 := D0;
reg := -1;
IF obj # NIL THEN
r := A6;
LOOP
IF regState.obj[r] = obj THEN reg := r; EXIT END;
(* DEC (r); IF r < D3 THEN EXIT END; *)
DEC (r); IF r < A0 THEN EXIT END;
END
END;
(*
IF reg < 0 THEN
r := D7;
LOOP
IF ~(r IN regState.regs) & (regState.obj[r] = NIL) THEN
reg := r; EXIT
END;
DEC (r); IF r < D3 THEN EXIT END;
END;
END;
*)
IF reg < 0 THEN
r := A3;
LOOP
IF ~(r IN regState.regs) & (regState.obj[r] = NIL) THEN
reg := r; EXIT
END;
DEC (r); IF r < A0 THEN EXIT END;
END;
END;
IF reg < 0 THEN
r := D7;
LOOP
IF ~(r IN regState.regs) THEN reg := r; EXIT END;
DEC (r); IF r < D3 THEN EXIT END;
END;
END;
IF reg < 0 THEN
r := A3;
LOOP
IF ~(r IN regState.regs) THEN reg := r; EXIT END;
DEC (r); IF r < A0 THEN EXIT END;
END;
END;
IF reg < 0 THEN
IF ~(A6 IN regState.regs) THEN reg := A6 END;
END;
IF reg < 0 THEN
OCS.Mark (215)
ELSE
x.a0 := reg; INCL (regState.regs, reg); regState.obj[reg] := obj;
INC (regState.count[reg])
END;
END GetAnyReg;
(*------------------------------------*)
PROCEDURE ReserveReg * (reg : LONGINT; obj : OCT.Object);
BEGIN (* ReserveReg *)
IF ~(reg IN regState.regs) THEN
INCL (regState.regs, reg);
IF reg IN AdrRegs THEN regState.obj[reg] := obj END;
regState.count[reg] := 1
ELSE
OCS.Mark (215)
END;
END ReserveReg;
(*------------------------------------*)
PROCEDURE UnReserveReg * (reg : LONGINT);
BEGIN (* UnReserveReg *)
IF (reg IN regState.regs) & (regState.count[reg] = 1) THEN
regState.count[reg] := 0;
EXCL (regState.regs, reg);
ELSE OCS.Mark (951)
END;
END UnReserveReg;
(*------------------------------------*)
PROCEDURE FreeRegs * (VAR r : RegState);
VAR reg : INTEGER;
BEGIN (* FreeRegs *)
regState.regs := r.regs;
FOR reg := 0 TO 15 DO
IF ~(reg IN regState.regs) THEN regState.count[reg] := 0 END
END
END FreeRegs;
(*------------------------------------*)
PROCEDURE FreeReg * (VAR x : OCT.Item);
VAR R : SET; r : LONGINT;
BEGIN (* FreeReg *)
IF x.mode IN {Reg, RegI, RegX, Push, Pop} THEN
r := x.a0;
IF (r IN regState.regs) & (regState.count[r] > 0) THEN
DEC (regState.count[r]);
IF regState.count[r] = 0 THEN EXCL (regState.regs, r) END
ELSE OCS.Mark (951)
END;
IF x.mode = RegX THEN
r := x.a2;
IF (r IN regState.regs) & (regState.count[r] > 0) THEN
DEC (regState.count[r]);
IF regState.count[r] = 0 THEN EXCL (regState.regs, r) END
ELSE OCS.Mark (951)
END
END
ELSIF x.mode IN {VarX, IndX} THEN
r := x.a2;
IF (r IN regState.regs) & (regState.count[r] > 0) THEN
DEC (regState.count[r]);
IF regState.count[r] = 0 THEN EXCL (regState.regs, r) END
ELSE OCS.Mark (951)
END
ELSIF x.mode = RList THEN
R := SYS.VAL (SET, x.a0);
IF (R * regState.regs) = R THEN
regState.regs := regState.regs - R;
FOR r := 0 TO 15 DO IF r IN R THEN regState.count[r] := 0 END END
ELSE OCS.Mark (951)
END
ELSE OCS.Mark (216)
END;
x.mode := Undef
END FreeReg;
(*------------------------------------*)
PROCEDURE InDataReg* ( obj : OCT.Object ) : BOOLEAN;
VAR i : INTEGER;
BEGIN (* InDataReg *)
IF obj = wasderef THEN obj := NIL END;
IF obj # NIL THEN
FOR i := D0 TO D7 DO IF regState.obj[i] = obj THEN RETURN TRUE END END
END;
RETURN FALSE
END InDataReg;
(*------------------------------------*)
PROCEDURE InAdrReg* ( obj : OCT.Object ) : BOOLEAN;
VAR i : INTEGER;
BEGIN (* InAdrReg *)
IF obj = wasderef THEN obj := NIL END;
IF obj # NIL THEN
FOR i := A0 TO A6 DO IF regState.obj[i] = obj THEN RETURN TRUE END END
END;
RETURN FALSE
END InAdrReg;
(*------------------------------------*)
PROCEDURE RememberReg* ( VAR x : OCT.Item; obj : OCT.Object );
BEGIN (* RememberReg *)
IF obj = wasderef THEN obj := NIL END;
IF obj # NIL THEN
IF (x.mode = Reg) & (x.a0 IN AdrRegs) THEN
regState.obj[x.a0] := obj
END
END;
END RememberReg;
(*------------------------------------*)
PROCEDURE ForgetReg* ( reg : LONGINT );
BEGIN (* ForgetReg *)
regState.obj[reg] := NIL
END ForgetReg;
(*------------------------------------*)
PROCEDURE ForgetObj* ( obj : OCT.Object );
VAR r : INTEGER;
BEGIN (* ForgetObj *)
IF obj = wasderef THEN obj := NIL END;
IF obj # NIL THEN
FOR r := D0 TO A6 DO
IF regState.obj[r] = obj THEN regState.obj[r] := NIL; RETURN END
END;
END;
END ForgetObj;
(*------------------------------------*)
PROCEDURE ForgetRegs*;
VAR r : INTEGER;
BEGIN (* ForgetRegs *)
FOR r := D0 TO A6 DO regState.obj[r] := NIL END
END ForgetRegs;
(*------------------------------------*)
PROCEDURE PutWord * (w : LONGINT);
BEGIN (* PutWord *)
IF (w < MIN (INTEGER)) OR (w > 65535) THEN OCS.Mark (958) END;
IF genCode THEN
IF codex >= CodeLength THEN OCS.Mark (231); codex := 0; pc := 0 END;
<*$ < NilChk- IndexChk- RangeChk- *>
code [codex] := SHORT (w);
<*$ > *>
INC (codex); INC (pc, 2)
END;
END PutWord;
(*------------------------------------*)
PROCEDURE PatchWord * (loc, w : LONGINT);
BEGIN (* PatchWord *)
IF (w < MIN (INTEGER)) OR (w > 65535) THEN OCS.Mark (958) END;
IF genCode THEN
IF loc >= pc THEN OCS.Mark (961); loc := 0 END;
loc := loc DIV 2;
<*$ < NilChk- IndexChk- RangeChk- *>
code [loc] := SYS.LOR (code [loc], SHORT (w))
<*$ > *>
END;
END PatchWord;
(*------------------------------------*)
PROCEDURE PutLong * (l : LONGINT);
BEGIN (* PutLong *)
IF codex >= CodeLength - 1 THEN OCS.Mark (231); codex := 0; pc := 0 END;
IF genCode THEN
<*$ < NilChk- IndexChk- RangeChk- *>
code [codex] := SHORT (l DIV 10000H); INC (codex);
code [codex] := SHORT (l MOD 10000H); INC (codex);
<*$ > *>
INC (pc, 4)
END;
END PutLong;
(*------------------------------------*)
PROCEDURE FindRef (label : OCT.Label; type : LONGINT) : Ref;
VAR ref : Ref;
BEGIN (* FindRef *)
ref := CurrCodeHunk.refs;
WHILE (ref # NIL) & ((ref.label^ # label^) OR (ref.type # type)) DO
ref := ref.next
END;
RETURN ref
END FindRef;
(*------------------------------------*)
PROCEDURE MakeRef (ref : Ref; label : OCT.Label; type : INTEGER);
VAR offset : Offset;
BEGIN (* MakeRef *)
IF genCode THEN
IF ref = NIL THEN
NEW (ref);
ref.next := CurrCodeHunk.refs; CurrCodeHunk.refs := ref;
ref.type := type; ref.label := label; ref.count := 0;
ref.offsets := NIL;
END;
NEW (offset);
offset.next := ref.offsets; ref.offsets := offset; INC (ref.count);
offset.n := pc - (CurrCodeHunk.start * 2);
END;
END MakeRef;
(*------------------------------------*)
PROCEDURE PutWordRef * (offset : INTEGER; label : OCT.Label);
BEGIN (* PutWordRef *)
IF label # NIL THEN
MakeRef (FindRef (label, wordRef), label, wordRef); PutWord (offset)
ELSE
OCS.Mark (964)
END
END PutWordRef;
(*------------------------------------*)
PROCEDURE PutLongRef * (offset : LONGINT; label : OCT.Label);
BEGIN (* PutLongRef *)
IF label # NIL THEN
MakeRef (FindRef (label, longRef), label, longRef); PutLong (offset)
ELSE
OCS.Mark (964)
END
END PutLongRef;
(*------------------------------------*)
PROCEDURE PutSmallRef * (offset : INTEGER; label : OCT.Label);
BEGIN (* PutSmallRef *)
IF label # NIL THEN
MakeRef (FindRef (label, smallRef), label, smallRef); PutWord (offset)
ELSE
OCS.Mark (964)
END
END PutSmallRef;
(*------------------------------------*)
PROCEDURE PutArg (VAR arg : Arg);
BEGIN (* PutArg *)
CASE arg.form OF
none :
|
word :
PutWord (arg.data)
|
long :
PutLong (arg.data)
|
wordRef, longRef, smallRef :
MakeRef (FindRef (arg.label, arg.form), arg.label, arg.form);
IF arg.form = longRef THEN PutLong (arg.data)
ELSE PutWord (arg.data)
END
ELSE
OCS.Mark (1008)
END;
END PutArg;
(*------------------------------------*)
PROCEDURE Argument
( VAR op : LONGINT; size : LONGINT; ea05 : BOOLEAN;
VAR item : OCT.Item; VAR arg : Arg );
VAR
form, mode, itemMode : INTEGER; reg, op2 : LONGINT;
regItem : OCT.Item; data : LONGINT; label : OCT.Label;
(*------------------------------------*)
PROCEDURE downlevel ();
VAR diff : INTEGER; op : LONGINT;
BEGIN (* downlevel *)
diff := level - item.lev;
GetAReg (regItem, NIL); reg := regItem.a0-8;
op := 206DH + SYS.LSH (reg, 9); (* MOVEA.L 8(A5), An *)
PutWord (op); PutWord (8);
op := 2068H + SYS.LSH (reg, 9) + reg; (* MOVEA.L 8(An), An *)
WHILE diff > 1 DO
PutWord (op); PutWord (8);
DEC (diff)
END;
mode := ARDisp; form := word; data := item.a0
END downlevel;
BEGIN (* Argument *)
form := none;
CASE item.mode OF
Var, VarX, Ind, IndX :
itemMode := item.mode;
IF (OCM.SmallData OR OCM.Resident) & (item.lev <= 0) THEN
(* Global variable in small data model *)
IF A4 IN regState.regs THEN OCS.Mark (235) END;
mode := ARDisp; reg := BP; form := smallRef; data := item.a0;
IF item.lev = 0 THEN label := OCT.VarLabel
ELSE label := OCT.GlbMod [-item.lev-1].varLab
END
ELSIF item.lev = 0 THEN (* Global variable of local module *)
IF OCS.pragma [OCS.longVars] OR (item.a0 > 32767)
OR (A4 IN regState.regs)
THEN
mode := Mode7; reg := AbsL; form := longRef;
label := OCT.VarLabel; data := item.a0
ELSIF item.a0 = 0 THEN
mode := ARInd; reg := BP; form := none
ELSE
mode := ARDisp; reg := BP; form := word; data := item.a0
END
ELSIF item.lev < 0 THEN (* Global variable of imported module *)
mode := Mode7; reg := AbsL; form := longRef;
label := OCT.GlbMod [-item.lev-1].varLab; data := item.a0
ELSIF item.lev = level THEN (* Local variable in procedure *)
IF item.a0 = 0 THEN
mode := ARInd; reg := FP; form := none
ELSE
mode := ARDisp; reg := FP; form := word; data := item.a0
END
ELSE (* Local variable in surrounding context *)
downlevel ();
IF itemMode = Var THEN
item.mode := RegI; item.a1 := item.a0; item.a0 := reg + 8;
item.obj := NIL;
Argument (op, size, ea05, item, arg);
RETURN
END
END;
arg.form := form; arg.data := data; arg.label := label;
IF itemMode = VarX THEN
GetAReg (regItem, NIL);
op2 :=
LEA + SYS.LSH (mode, 3) + reg
+ SYS.LSH (regItem.a0-8, 9); (* LEA <item>, An *)
PutWord (op2); PutArg (arg);
item.mode := RegX; item.a0 := regItem.a0; item.a1 := 0;
item.obj := NIL;
Argument (op, size, ea05, item, arg);
RETURN
ELSIF itemMode # Var THEN
GetAReg (regItem, NIL);
op2 :=
2040H + SYS.LSH (mode, 3) + reg
+ SYS.LSH (regItem.a0 - 8, 9);
PutWord (op2); PutArg (arg); (* MOVEA.L, <item>, An *)
reg := regItem.a0 - 8;
IF itemMode = IndX THEN item.mode := RegX
ELSE item.mode := RegI
END;
item.a0 := regItem.a0; item.obj := NIL;
Argument (op, size, ea05, item, arg);
RETURN
END
|
VarR :
label := NIL; data := 0;
IF item.a0 < A0 THEN form := DReg; reg := item.a0
ELSE form := ARDir; reg := item.a0 - 8
END;
item.mode := Reg; item.a1 := 0
|
IndR :
label := NIL; data := 0;
IF item.a0 < A0 THEN
reg := item.a0; GetAReg (regItem, NIL);
op2 :=
2040H + SYS.LSH (mode, 3) + reg
+ SYS.LSH (regItem.a0 - 8, 9);
PutWord (op2); PutArg (arg); (* MOVEA.L, <item>, An *)
form := ARInd; reg := regItem.a0 - 8;
item.mode := RegI; item.a0 := regItem.a0; item.a1 := 0
ELSE
form := ARInd; reg := item.a0 - 8;
item.mode := RegI; item.a1 := 0
END
|
RegI :
IF ~(item.a0 IN AdrRegs) THEN OCS.Mark (215); item.a0 := A0 END;
reg := item.a0 - 8;
IF item.a1 = 0 THEN mode := ARInd; form := none
ELSIF (item.a1 < -32768) OR (item.a1 > 32767) THEN
GetAnyReg (regItem, NIL);
IF regItem.a0 < A0 THEN (* MOVE.L #offset, Dn *)
op2 := 203CH + SYS.LSH (regItem.a0, 9)
ELSE (* MOVEA.L #offset, An *)
op2 := 207CH + SYS.LSH (regItem.a0 - 8, 9)
END;
PutWord (op2); PutLong (item.a1);
item.mode := RegX; item.a1 := 0; item.a2 := regItem.a0;
item.wordIndex := FALSE;
Argument (op, size, ea05, item, arg);
RETURN
ELSE
mode := ARDisp; form := word; data := item.a1
END
|
RegX :
IF ~(item.a0 IN AdrRegs) THEN OCS.Mark (215); item.a0 := A0 END;
mode := ARDisX; reg := item.a0 - 8;
IF (item.a1 < -128) OR (item.a1 > 127) THEN
IF item.a2 < A0 THEN (* ADDI.z #offset, Rn *)
IF item.wordIndex THEN op2 := 0640H + item.a2
ELSE op2 := 0680H + item.a2
END
ELSE (* ADDA.Z #offset, Rn *)
IF item.wordIndex THEN op2 := 0D0FCH
ELSE op2 := 0D1FCH
END;
op2 := op2 + SYS.LSH (item.a2 - 8, 9)
END;
PutWord (op2);
IF item.wordIndex THEN PutWord (item.a1)
ELSE PutLong (item.a1)
END;
item.a1 := 0
END;
form := word;
data := SYS.AND (item.a1, 0FFH); (* Displacement *)
data := SYS.LOR (data, SYS.LSH (item.a2 MOD 8, 12));
(* Index reg. *)
IF item.a2 >= A0 THEN data := SYS.LOR (data, 8000H)
END; (* Addr. Reg. *)
IF ~item.wordIndex THEN data := SYS.LOR (data, 800H) (* Long reg. *)
END;
|
Lab, LabI :
mode := Mode7;
IF item.mode = Lab THEN reg := AbsL ELSE reg := Imm END;
IF item.a1 = W THEN form := wordRef
ELSIF item.a1 = L THEN form := longRef
ELSE OCS.Mark (957); form := longRef
END;
data := item.a0; label := item.label
|
Abs :
mode := Mode7;
IF (-32768 <= item.a0) & (item.a0 <= 32767) THEN
reg := AbsW; form := word
ELSE
reg := AbsL; form := long
END;
data := item.a0
|
Con :
IF (item.typ = OCT.stringtyp) OR (item.typ = OCT.tagtyp) THEN
IF item.a0 < 0 THEN OCS.Mark (962) END;
IF OCM.SmallData THEN
IF A4 IN regState.regs THEN OCS.Mark (235) END;
mode := ARDisp; reg := BP; form := smallRef; data := item.a0;
ELSE
mode := Mode7; reg := AbsL; form := longRef; data := item.a0;
END;
label := item.label
ELSE
mode := Mode7; reg := Imm;
IF size < L THEN form := word ELSE form := long END;
data := item.a0
END
|
Push, Pop :
IF ~(item.a0 IN AdrRegs) THEN OCS.Mark (215); item.a0 := A0 END;
IF item.mode = Push THEN mode := ARPre ELSE mode := ARPost END;
reg := item.a0 - 8; form := none
|
Reg :
IF item.a0 IN DataRegs THEN
mode := DReg; reg := item.a0; form := none
ELSE
mode := ARDir; reg := item.a0 - 8; form := none
END
|
XProc, LProc, CallBack :
mode := Mode7; data := 0; label := item.obj.label;
IF item.lev < 0 THEN reg := AbsL; form := longRef (* Imported proc. *)
ELSE reg := AbsW; form := wordRef
END
|
M2Proc, CProc, AProc :
mode := Mode7; data := 0; label := item.obj.label;
reg := AbsL; form := longRef
|
RList :
arg.form := word; arg.data := item.a0;
RETURN
|
ELSE
form := none; OCS.Mark (126);
RETURN
END; (* CASE item.mode *)
arg.form := form; arg.data := data; arg.label := label;
IF ea05 THEN op := op + SYS.LSH (mode, 3) + reg
ELSE op := op + SYS.LSH (mode, 6) + SYS.LSH (reg, 9)
END
END Argument;
(*------------------------------------*)
PROCEDURE PutF1 * (op : LONGINT; size : LONGINT; VAR item : OCT.Item);
(*
Instruction format #1: xxxxxxxxsseeeeee
Instructions: CLR, NEG, NOT, TST
*)
VAR arg : Arg;
BEGIN (* PutF1 *)
op := op + SYS.LSH ((size DIV 2), 6);
Argument (op, size, TRUE, item, arg);
PutWord (op); PutArg (arg)
END PutF1;
(*------------------------------------*)
PROCEDURE PutF2 * (op : LONGINT; VAR src : OCT.Item; reg : LONGINT);
(*
Instruction format #2: xxxxrrrxxxeeeeee
Instructions: LEA, DIVS, MULS, CHK
*)
VAR arg : Arg;
BEGIN (* PutF2 *)
op := op + SYS.LSH (reg MOD 8, 9);
Argument (op, W, TRUE, src, arg);
PutWord (op); PutArg (arg)
END PutF2;
(*------------------------------------*)
PROCEDURE PutF3 * (op : LONGINT; VAR item : OCT.Item);
(*
Instruction format #3: xxxxxxxxxxeeeeee
Instructions: PEA, JSR, JMP, Scc
*)
VAR arg : Arg;
BEGIN (* PutF3 *)
Argument (op, W, TRUE, item, arg);
PutWord (op); PutArg (arg)
END PutF3;
(*------------------------------------*)
PROCEDURE Bit * (op : LONGINT; VAR src, dst : OCT.Item);
(*
Instruction format #2: xxxxrrrxxxeeeeee
Instruction format #3: xxxxxxxxxxeeeeee
Instructions: BTST, BCLR, BSET
*)
VAR arg : Arg;
BEGIN (* Bit *)
IF src.mode = Reg THEN
op := SYS.LOR (op, SYS.LOR (100H, SYS.LSH (src.a0, 9)))
ELSE
op := SYS.LOR (op, 800H)
END;
Argument (op, W, TRUE, dst, arg);
PutWord (op); IF src.mode = Con THEN PutWord (src.a0) END;
PutArg (arg)
END Bit;
(*------------------------------------*)
PROCEDURE Move * (size : LONGINT; VAR src, dst : OCT.Item);
VAR arg1, arg2 : Arg; op, reg : LONGINT; rlist1, rlist2 : SET;
BEGIN (* Move *)
IF (src.mode = Reg) & (dst.mode = Reg) & (src.a0 = dst.a0) THEN
RETURN
END;
IF src.mode = RList THEN (* MOVEM Registers to EA *)
IF size = L THEN op := 48C0H ELSE op := 4880H END;
Argument (op, size, TRUE, dst, arg1);
IF dst.mode = Push THEN
(* Reverse the register list first *)
reg := 0;
rlist1 := SYS.VAL (SET, src.a0); rlist2 := {};
WHILE reg <= A7 DO
IF reg IN rlist1 THEN INCL (rlist2, 15 - reg) END;
INC (reg)
END;
src.a0 := SYS.VAL (LONGINT, rlist2)
END;
PutWord (op); PutWord (src.a0); PutArg (arg1)
ELSIF dst.mode = RList THEN (* MOVEM EA to Registers *)
IF size = L THEN op := 4CC0H ELSE op := 4C80H END;
Argument (op, size, TRUE, src, arg1);
PutWord (op); PutWord (dst.a0); PutArg (arg1)
ELSIF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
IF (src.mode = Con) & (src.a0 = 0) THEN (* SUBA.Z <dst>, <dst> *)
reg := dst.a0 - 8; op := 90C8H;
IF size = L THEN op := SYS.LOR (op, 100H)
ELSIF size = B THEN OCS.Mark (957)
END;
op := SYS.LOR (op, SYS.LOR (SYS.LSH (reg, 9), reg));
PutWord (op)
ELSE (* MOVEA.Z <src>, <dst> *)
IF size = L THEN
op := SYS.LOR (2040H, SYS.LSH (dst.a0 MOD 8, 9))
ELSIF size = W THEN
op := SYS.LOR (3040H, SYS.LSH (dst.a0 MOD 8, 9))
ELSE
OCS.Mark (957); op := 3040H
END;
Argument (op, size, TRUE, src, arg1); PutWord (op); PutArg (arg1)
END
ELSIF
(dst.mode = Reg) & (dst.a0 IN DataRegs) & (src.mode = Con)
& (src.a0 >= -128) & (src.a0 <= 127)
THEN (* MOVEQ #<src>, <dst> *)
op := SYS.LOR (7000H, SYS.LSH (dst.a0, 9));
op := SYS.LOR (op, SYS.AND (src.a0, 0FFH));
PutWord (op)
ELSIF (src.mode = Con) & (src.a0 = 0) THEN (* CLR.z <dst> *)
PutF1 (CLR, size, dst)
ELSE (* MOVE.z <src>, <dst> *)
IF size = L THEN op := 2000H
ELSIF size = W THEN op := 3000H
ELSIF size = B THEN op := 1000H
ELSE
OCS.Mark (957); op := 1000H
END;
Argument (op, size, TRUE, src, arg1);
Argument (op, size, FALSE, dst, arg2);
PutWord (op); PutArg (arg1); PutArg (arg2)
END
END Move;
(*------------------------------------*)
PROCEDURE PutF7 * (op : LONGINT; size, src : LONGINT; VAR dst : OCT.Item);
(*
Instruction format #7: xxxxdddxsseeeeee
Instructions: ADDQ, SUBQ
*)
VAR arg : Arg;
BEGIN (* PutF7 *)
IF (src > 0) & (src <= 8) THEN
op := SYS.LOR (op, SYS.LSH ((size DIV 2), 6));
op := SYS.LOR (op, SYS.LSH (src MOD 8, 9));
Argument (op, size, TRUE, dst, arg); PutWord (op); PutArg (arg)
ELSE
OCS.Mark (957)
END; (* ELSE *)
END PutF7;
(*------------------------------------*)
PROCEDURE PutF6 * (op, size : LONGINT; VAR src, dst : OCT.Item);
(*
Instruction format #6: xxxxxxxxsseeeeee
Instructions: ORI, SUBI, CMPI, EORI, ANDI, ADDI
Instructions: ADDQ, SUBQ
*)
VAR arg : Arg;
BEGIN (* PutF6 *)
IF ((op = ADDI) OR (op = SUBI)) & (src.a0 > 0) & (src.a0 < 9) THEN
IF op = ADDI THEN op := ADDQ ELSE op := SUBQ END;
PutF7 (op, size, src.a0, dst)
ELSE
op := SYS.LOR (op, SYS.LSH ((size DIV 2), 6));
Argument (op, size, TRUE, dst, arg); PutWord (op);
IF src.mode = LabI THEN PutLongRef (src.a0, src.label)
ELSIF size = L THEN PutLong (src.a0)
ELSE PutWord (src.a0)
END;
PutArg (arg)
END
END PutF6;
(*------------------------------------*)
PROCEDURE PutF5 * (op, size : LONGINT; VAR src, dst : OCT.Item);
(*
Instruction format #5: xxxxrrrmmmeeeeee
Instructions: OR, SUB, SUBA, CMP, CMPA, EOR, AND, ADD, ADDA, ORI,
SUBI, CMPI, EORI, ANDI, ADDI, ADDQ, SUBQ
*)
VAR arg : Arg;
BEGIN (* PutF5 *)
IF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
IF size = L THEN op := SYS.LOR (op, 1C0H)
ELSIF size = W THEN op := SYS.LOR (op, 0C0H)
ELSE OCS.Mark (957)
END;
op := SYS.LOR (op, SYS.LSH (dst.a0 - 8, 9));
Argument (op, size, TRUE, src, arg)
ELSIF (src.mode = Con) OR (src.mode = LabI) THEN
IF op = iOR THEN op := ORI
ELSIF op = SUB THEN op := SUBI
ELSIF op = CMP THEN op := CMPI
ELSIF op = EOR THEN op := EORI
ELSIF op = AND THEN op := ANDI
ELSIF op = ADD THEN op := ADDI
ELSE OCS.Mark (956)
END;
PutF6 (op, size, src, dst);
RETURN
ELSIF (op # EOR) & (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
op := SYS.LOR (op, SYS.LSH (size DIV 2, 6));
op := SYS.LOR (op, SYS.LSH (dst.a0, 9));
Argument (op, size, TRUE, src, arg)
ELSE
op := SYS.LOR (op, SYS.LSH (size DIV 2, 6));
op := SYS.LOR (SYS.LOR (op, 100H), SYS.LSH (src.a0, 9));
Argument (op, size, TRUE, dst, arg)
END;
PutWord (op); PutArg (arg)
END PutF5;
(*------------------------------------*)
PROCEDURE Shift * (op, size : LONGINT; VAR count, reg : OCT.Item);
(*
Instruction format #5: xxxxrrrxssxxxrrr
Instructions: ASL, ASR, LSL, LSR, ROL, ROR
*)
VAR arg : Arg;
BEGIN (* Shift *)
IF (reg.mode = Reg) & (reg.a0 IN DataRegs) THEN
op := SYS.LOR (op, SYS.LSH ((size DIV 2), 6));
op := SYS.LOR (op, reg.a0);
IF (count.mode = Reg) & (count.a0 IN DataRegs) THEN
op := SYS.LOR (op, 20H);
op := SYS.LOR (op, SYS.LSH (count.a0, 9))
ELSIF count.mode = Con THEN
IF (count.a0 > 0) & (count.a0 <= 8) THEN
op := SYS.LOR (op, SYS.LSH (count.a0 MOD 8, 9))
ELSE OCS.Mark (957)
END;
ELSE OCS.Mark (956)
END;
PutWord (op)
ELSE OCS.Mark (956)
END;
END Shift;
(*------------------------------------*)
PROCEDURE SaveRegisters0 (regs : SET);
VAR numRegs, reg, lastReg, op : INTEGER; rlist : SET;
BEGIN (* SaveRegisters0 *)
IF regs # {} THEN
numRegs := 0; reg := 0;
WHILE reg <= A7 DO
IF reg IN regs THEN lastReg := reg; INC (numRegs) END;
INC (reg)
END;
IF numRegs = 1 THEN
IF lastReg IN DataRegs THEN (* MOVE.L Dn, -(A7) *)
op := SYS.LOR (2F00H, lastReg)
ELSE (* MOVE.L An, -(A7) *)
op := SYS.LOR (2F08H, lastReg - 8)
END;
PutWord (op)
ELSE (* MOVEM.L <regs>, -(A7) *)
(* Reverse the register list first *)
reg := 0; rlist := {};
WHILE reg <= lastReg DO
IF reg IN regs THEN INCL (rlist, 15 - reg) END;
INC (reg)
END;
PutWord (48E7H); PutWord (SYS.VAL (LONGINT, rlist))
END
END
END SaveRegisters0;
(*------------------------------------*)
PROCEDURE SaveRegisters *
( VAR saved : RegState;
VAR x : OCT.Item;
mask : SET );
VAR r : INTEGER;
BEGIN (* SaveRegisters *)
(* Temporarily reserve A4 and/or A5 if in mask *)
regState.regs := regState.regs + (mask * {A4,A5});
saved := regState; saved.regs := saved.regs * mask;
IF x.mode IN {Reg, RegI, RegX} THEN EXCL (saved.regs, x.a0) END;
IF x.mode IN {VarX, IndX, RegX} THEN EXCL (saved.regs, x.a2) END;
SaveRegisters0 (saved.regs);
regState.regs := regState.regs - saved.regs;
FOR r := 0 TO 15 DO
IF r IN saved.regs THEN regState.count[r] := 0 END;
END
END SaveRegisters;
(*------------------------------------*)
PROCEDURE LoadRegParams1 * (VAR saved : RegState; VAR x : OCT.Item);
VAR d0 : OCT.Item; inD0 : BOOLEAN; r : INTEGER;
BEGIN (* LoadRegParams1 *)
inD0 := (x.mode = Reg) & (x.a0 = D0);
saved := regState; saved.regs := saved.regs * ScratchRegs;
IF inD0 THEN EXCL (saved.regs, D0) END;
SaveRegisters0 (saved.regs);
regState.regs := regState.regs - saved.regs;
FOR r := 0 TO 15 DO
IF r IN saved.regs THEN regState.count[r] := 0 END;
END;
IF ~inD0 THEN
d0.mode := Reg; d0.a0 := D0; Move (x.typ^.size, x, d0)
END
END LoadRegParams1;
(*------------------------------------*)
PROCEDURE LoadRegParams2 * (VAR saved : RegState; VAR x, y : OCT.Item);
VAR d0, d1, t : OCT.Item; r : INTEGER;
BEGIN (* LoadRegParams2 *)
saved := regState; saved.regs := saved.regs * ScratchRegs;
IF (x.mode = Reg) & (x.a0 IN {D0, D1}) THEN EXCL (saved.regs, x.a0) END;
IF (y.mode = Reg) & (y.a0 IN {D0, D1}) THEN EXCL (saved.regs, y.a0) END;
SaveRegisters0 (saved.regs);
regState.regs := regState.regs - saved.regs;
FOR r := 0 TO 15 DO
IF r IN saved.regs THEN regState.count[r] := 0 END;
END;
d0.mode := Reg; d0.a0 := D0; d1.mode := Reg; d1.a0 := D1;
IF (y.mode = Reg) & (y.a0 = D0) THEN
IF (x.mode = Reg) & (x.a0 = D1) THEN
GetDReg (t, NIL); Move (x.typ^.size, x, t); x.a0 := t.a0;
EXCL (regState.regs, D1); regState.count[D1] := 0
END;
Move (y.typ^.size, y, d1); y.a0 := D1;
EXCL (regState.regs, D0); regState.count[D0] := 0;
INCL (regState.regs, D1); regState.count[D1] := 1
END;
IF ~((x.mode = Reg) & (x.a0 = D0)) THEN Move (x.typ^.size, x, d0) END;
IF ~((y.mode = Reg) & (y.a0 = D1)) THEN Move (y.typ^.size, y, d1) END
END LoadRegParams2;
(*------------------------------------*)
PROCEDURE CallKernel * ( proc : INTEGER );
BEGIN (* CallKernel *)
IF OCM.SmallCode THEN
PutWord (BSR); PutWordRef (0, kernelLab [proc])
ELSE
PutWord (JSR + 039H); PutLongRef (0, kernelLab [proc])
END;
END CallKernel;
(*------------------------------------*)
PROCEDURE RestoreRegisters * (VAR saved : RegState; VAR x : OCT.Item);
VAR
numRegs, op, reg, lastReg : INTEGER; y : OCT.Item; rlist : SET;
restyp : OCT.Struct;
BEGIN (* RestoreRegisters *)
regState.regs := regState.regs + saved.regs;
FOR reg := D0 TO A6 DO
IF reg IN saved.regs THEN
regState.obj[reg] := saved.obj[reg];
regState.count[reg] := saved.count[reg]
END;
END;
IF x.mode IN {XProc, LProc, TProc, M2Proc, CProc, AProc, CallBack} THEN
restyp := x.typ
ELSIF (x.mode IN {Var..RegX}) & (x.typ.form = ProcTyp) THEN
restyp := x.typ.BaseTyp
ELSE
restyp := NIL
END;
IF
(restyp # NIL) & (restyp.form = Pointer) & (restyp.size > OCM.PtrSize)
THEN (* PROCEDURE return type is POINTER TO ARRAY OF ... *)
reg := 0; rlist := {};
WHILE (reg * 4) < restyp.size DO INCL (rlist, reg); INC (reg) END;
IF (rlist * regState.regs) # {} THEN OCS.Mark (967) END;
regState.regs := regState.regs + rlist;
x.mode := RList; x.a0 := SYS.VAL (LONGINT, rlist)
ELSE
y := x; x.mode := Reg; x.a0 := D0;
IF (D0 IN saved.regs) OR (y.mode = Reg) THEN
IF (y.mode # Reg) OR ~(y.a0 IN DataRegs) THEN
GetDReg (y, NIL)
END;
IF y.a0 # 0 THEN Move (L, x, y); x.a0 := y.a0 END;
ELSE
INCL (regState.regs, D0); regState.count[D0] := 1
END
END;
IF saved.regs # {} THEN
numRegs := 0; reg := 0;
WHILE reg <= A7 DO
IF reg IN saved.regs THEN lastReg := reg; INC (numRegs) END;
INC (reg)
END; (* WHILE *)
IF numRegs = 1 THEN
IF lastReg IN DataRegs THEN (* MOVE.L (A7)+, Dn *)
op := SYS.LOR (201FH, SYS.LSH (lastReg, 9))
ELSE (* MOVEA.L (A7)+, An *)
op := SYS.LOR (205FH, SYS.LSH (lastReg - 8, 9))
END;
PutWord (op)
ELSE (* MOVEM.L (A7)+, <regs> *)
PutWord (4CDFH); PutWord (SYS.VAL (LONGINT, saved.regs))
END
END; (* IF *)
regState.regs := regState.regs - {A4,A5} (* Mask out system registers *)
END RestoreRegisters;
(*------------------------------------*)
PROCEDURE fixup * (loc : LONGINT); (* enter pc at loc *)
VAR offset : LONGINT;
BEGIN (* fixup *)
IF genCode THEN
offset := pc - loc;
IF (offset < MIN (INTEGER)) OR (offset > MAX (INTEGER)) THEN
OCS.Mark (955); offset := 0
END;
<*$ < NilChk- IndexChk- RangeChk- *>
code [loc DIV 2] := SHORT (offset)
<*$ > *>
END
END fixup;
(*------------------------------------*)
PROCEDURE FixLink * (L : LONGINT);
VAR L1 : LONGINT;
BEGIN (* FixLink *)
IF genCode THEN
WHILE L # 0 DO
<*$ < NilChk- IndexChk- *>
L1 := code [L DIV 2]; fixup (L); L := L1
<*$ > *>
END
END
END FixLink;
(*------------------------------------*)
PROCEDURE FixupWith * (L, val : LONGINT);
VAR x : LONGINT;
BEGIN (* FixupWith *)
IF genCode THEN
<*$ < NilChk- IndexChk- RangeChk- *>
code [L DIV 2] := SHORT (val)
<*$ > *>
END
END FixupWith;
(*------------------------------------*)
PROCEDURE FixLinkWith * (L, val : LONGINT);
VAR L1 : LONGINT;
BEGIN (* FixLinkWith *)
IF genCode THEN
WHILE L # 0 DO
<*$ < NilChk- IndexChk- *>
L1 := code [L DIV 2];
<*$ > *>
FixupWith (L, val - L); L := L1
END
END
END FixLinkWith;
(*------------------------------------*)
PROCEDURE MergedLinks * (L0, L1 : LONGINT): LONGINT;
VAR L2, L3 : LONGINT;
BEGIN (* MergedLinks *)
(* merge chains of the two operands of AND and OR *)
IF L0 # 0 THEN
IF genCode THEN
L2 := L0;
LOOP
<*$ < NilChk- IndexChk- *>
L3 := code [L2 DIV 2];
<*$ > *>
IF L3 = 0 THEN EXIT END;
L2 := L3
END; (* LOOP *)
<*$ < NilChk- IndexChk- RangeChk- *>
code [L2 DIV 2] := SHORT (L1);
<*$ > *>
END;
RETURN L0
ELSE
RETURN L1
END; (* ELSE *)
END MergedLinks;
(*------------------------------------*)
PROCEDURE invertedCC * (cc : LONGINT) : LONGINT;
BEGIN (* invertedCC *)
IF ODD (cc) THEN RETURN cc - 1
ELSE RETURN cc + 1
END
END invertedCC;
(*------------------------------------*)
PROCEDURE Trap * (n : INTEGER);
BEGIN (* Trap *)
IF n = OverflowCheck THEN
PutWord (TRAPV); (* TRAPV *)
PutWord (06008H); (* BRA.S 1$ *)
ELSE
PutWord (TRAP + n) (* TRAP #n *)
END;
IF OCM.Force THEN
PutWord (NOP); PutWord (NOP); PutWord (NOP); PutWord (NOP)
ELSE
PutLongRef (0, OCT.ConstLabel); (* DC.L ModuleName *)
PutWord (OCS.line); (* DC.W line *)
PutWord (OCS.col); (* DC.W col *)
END;
(* 1$ *)
END Trap;
(*------------------------------------*)
PROCEDURE TrapCC * (n, cc : INTEGER);
BEGIN (* TrapCC *)
IF cc # T THEN
(* Branch over the following TRAP instruction (10 bytes) *)
PutWord (Bcc + (invertedCC (cc) * 100H) + 10)
END;
Trap (n)
END TrapCC;
(*------------------------------------*)
PROCEDURE TrapLink * ( n, cc : INTEGER; L : LONGINT );
BEGIN (* TrapLink *)
IF cc # T THEN
(* Branch over the following TRAP instruction (10 bytes) *)
PutWord (Bcc + (invertedCC (cc) * 100H) + 10)(* Bcc 2$ *)
END;
PatchWord (L, pc - L - 2); PutWord (TRAP + n); (* 1$ TRAP #n *)
IF OCM.Force THEN
PutWord (NOP); PutWord (NOP); PutWord (NOP); PutWord (NOP)
ELSE
PutLongRef (0, OCT.ConstLabel); (* DC.L ModuleName *)
PutWord (OCS.line); (* DC.W line *)
PutWord (OCS.col); (* DC.W col *)
END;
(* 2$ *)
END TrapLink;
(*------------------------------------*)
PROCEDURE TypeTrap * ( L : LONGINT );
BEGIN (* TypeTrap *)
PutWord (600AH); (* BRA.S 1$ *)
FixLink (L); PutWord (TRAP + TypeCheck); (* L: TRAP #TypeCheck *)
IF OCM.Force THEN
PutWord (NOP); PutWord (NOP); PutWord (NOP); PutWord (NOP)
ELSE
PutLongRef (0, OCT.ConstLabel); (* DC.L ModuleName *)
PutWord (OCS.line); (* DC.W line *)
PutWord (OCS.col); (* DC.W col *)
END;
(* 1$ *)
END TypeTrap;
(*------------------------------------*)
PROCEDURE PutCHK* ( VAR bound : OCT.Item; reg : LONGINT );
BEGIN (* PutCHK *)
PutF2 (CHK, bound, reg);
PutWord (06008H); (* BRA.S 1$ *)
IF OCM.Force THEN
PutWord (NOP); PutWord (NOP); PutWord (NOP); PutWord (NOP)
ELSE
PutLongRef (0, OCT.ConstLabel); (* DC.L ModuleName *)
PutWord (OCS.line); (* DC.W line *)
PutWord (OCS.col); (* DC.W col *)
END;
(* 1$ *)
END PutCHK;
(*------------------------------------*)
PROCEDURE GlobalPtrs * () : BOOLEAN;
VAR obj : OCT.Object;
(*------------------------------------*)
PROCEDURE FindPtrs (typ : OCT.Struct);
VAR btyp : OCT.Struct; fld : OCT.Object; i, n : LONGINT;
BEGIN (* FindPtrs *)
IF
((typ.form = Pointer) & (typ.sysflg = OberonFlag))
OR (typ.form = PtrTyp)
THEN
INC (numPtrs)
ELSIF (typ.form = Record) & (typ.sysflg = OberonFlag) THEN
btyp := typ.BaseTyp; IF btyp # NIL THEN FindPtrs (btyp) END;
fld := typ.link;
WHILE fld # NIL DO
IF fld.mode = Fld THEN
IF fld.name < 0 THEN INC (numPtrs) (* Hidden pointer field *)
ELSE FindPtrs (fld.typ)
END;
END;
fld := fld.left
END
ELSIF typ.form = Array THEN
btyp := typ.BaseTyp; n := typ.n;
WHILE btyp.form = Array DO n := btyp.n * n; btyp := btyp.BaseTyp END;
IF btyp.form IN {Pointer, PtrTyp, Record} THEN
i := 0; WHILE i < n DO FindPtrs (btyp); INC (i) END
END
END
END FindPtrs;
BEGIN (* GlobalPtrs *)
numPtrs := 0; obj := OCT.topScope.right;
WHILE obj # NIL DO
IF obj.mode = Var THEN FindPtrs (obj.typ) END;
obj := obj.link
END;
RETURN (numPtrs # 0)
END GlobalPtrs;
(*------------------------------------*)
PROCEDURE NumProcs (typ : OCT.Struct) : LONGINT;
VAR n : LONGINT; obj : OCT.Object;
BEGIN (* NumProcs *)
n := 0;
REPEAT
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.a0 > n) THEN n := obj.a0 END;
obj := obj.left
END;
typ := typ.BaseTyp
UNTIL typ = NIL;
RETURN n
END NumProcs;
(*------------------------------------*)
PROCEDURE ProcLab (typ : OCT.Struct; pno : LONGINT) : OCT.Label;
VAR obj : OCT.Object;
BEGIN (* ProcLab *)
LOOP
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.a0 = pno) THEN
RETURN obj.label
END;
obj := obj.left
END;
typ := typ.BaseTyp;
IF typ = NIL THEN HALT (929) END
END;
END ProcLab;
(*------------------------------------*)
PROCEDURE AllocSlots*;
VAR
slot, nextSlot : LONGINT; obj : OCT.Object; typ : OCT.Struct;
i : INTEGER; pos1, pos2, offset : LONGINT;
PROCEDURE FindSlot ( typ : OCT.Struct; name : LONGINT ) : LONGINT;
VAR obj : OCT.Object;
BEGIN (* FindSlot *)
LOOP
IF typ = NIL THEN RETURN -1 END;
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.name = name) THEN RETURN obj.a0 END;
obj := obj.left
END;
typ := typ.BaseTyp
END
END FindSlot;
BEGIN (* AllocSlots *)
FOR i := 0 TO typex - 1 DO
typ := type [i];
IF (typ.form = Record) & (typ.sysflg = OberonFlag) THEN
nextSlot := OCT.NextProc (typ);
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.a0 < 0) THEN
slot := FindSlot (typ.BaseTyp, obj.name);
IF slot < 0 THEN slot := nextSlot; INC (nextSlot) END;
obj.a0 := slot; offset := slot * (-4);
IF offset < MIN (INTEGER) THEN OCS.Mark (955); offset := 0 END;
pos1 := obj.a2;
WHILE pos1 # 1 DO
<*$ < NilChk- IndexChk- RangeChk- *>
pos2 := code [pos1 DIV 2]; code [pos1 DIV 2] := SHORT (offset);
<*$ > *>
pos1 := pos2
END; (* WHILE *)
END; (* IF *)
obj := obj.left
END; (* WHILE *)
END; (* IF *)
END (* FOR *)
END AllocSlots;
(*------------------------------------*)
PROCEDURE OutCode * (FName : ARRAY OF CHAR; key, datasize : LONGINT);
VAR
ObjFile : Files.File;
out : Files.Rider;
blockType, res, N : LONGINT;
codeHunk : CodeHunk;
(* ---------------------------------- *)
PROCEDURE OutName (type : INTEGER; name : ARRAY OF CHAR);
VAR len, char, pad : LONGINT;
<*$CopyArrays-*>
BEGIN (* OutName *)
len := SYS.STRLEN (name);
pad := (((len + 3) DIV 4) * 4) - len;
N := SYS.LSH (LONG (type), 24) + ((len + 3) DIV 4);
Files.WriteBytes (out, N, 4);
char := 0;
WHILE char < len DO
Files.Write (out, name [char]);
INC (char);
END;
WHILE pad > 0 DO Files.Write (out, 0X); DEC (pad) END;
END OutName;
(* ---------------------------------- *)
PROCEDURE OutHunkUnit (name : ARRAY OF CHAR);
<*$CopyArrays-*>
BEGIN (* OutHunkUnit *)
blockType := hunkUnit;
Files.WriteBytes (out, blockType, 4);
OutName (0, name);
END OutHunkUnit;
(*------------------------------------*)
PROCEDURE OutHunkName (name : ARRAY OF CHAR);
<*$CopyArrays-*>
BEGIN (* OutHunkName *)
blockType := hunkName;
Files.WriteBytes (out, blockType, 4);
OutName (0, name);
END OutHunkName;
(*------------------------------------*)
PROCEDURE OutDef0 (label : ARRAY OF CHAR; offset : LONGINT);
<*$CopyArrays-*>
BEGIN (* OutDef0 *)
OutName (extDef, label);
Files.WriteBytes (out, offset, 4)
END OutDef0;
(*------------------------------------*)
PROCEDURE OutDef (def : Def);
BEGIN (* OutDef *)
OutDef0 (def.object.label^, def.offset)
END OutDef;
(*------------------------------------*)
PROCEDURE OutRef (ref : Ref);
VAR type : INTEGER; offset : Offset;
BEGIN (* OutRef *)
IF ref.type = longRef THEN type := extRef32
ELSIF ref.type = wordRef THEN type := extRef16
ELSIF ref.type = smallRef THEN type := extDExt16
ELSE OCS.Mark (959)
END;
OutName (type, ref.label^);
Files.WriteBytes (out, ref.count, 4);
offset := ref.offsets;
WHILE offset # NIL DO
Files.WriteBytes (out, offset.n, 4);
offset := offset.next
END
END OutRef;
(*------------------------------------*)
PROCEDURE OutCodeHunk (codeHunk : CodeHunk);
(*------------------------------------*)
PROCEDURE OutHunkCode ();
VAR pos, len : LONGINT; pad : INTEGER;
BEGIN (* OutHunkCode *)
blockType := hunkCode;
Files.WriteBytes (out, blockType, 4);
N := (codeHunk.length + 1) DIV 2;
Files.WriteBytes (out, N, 4);
pos := codeHunk.start; len := codeHunk.length;
WHILE len > 0 DO
<*$ < NilChk- IndexChk- *>
Files.WriteBytes (out, code [pos], 2);
<*$ > *>
INC (pos); DEC (len);
END; (* WHILE *)
IF ODD (codeHunk.length) THEN
pad := NOP; (* Output a NOP, purely for the benefit of ninfo *)
Files.WriteBytes (out, pad, 2);
END
END OutHunkCode;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
VAR ref : Ref; def : Def;
BEGIN (* OutHunkExt *)
blockType := hunkExt; Files.WriteBytes (out, blockType, 4);
IF codeHunk = InitCodeHunk THEN OutDef0 (OCT.InitLabel^, 0) END;
def := codeHunk.defs;
WHILE def # NIL DO OutDef (def); def := def.next END;
ref := codeHunk.refs;
WHILE ref # NIL DO OutRef (ref); ref := ref.next END;
N := 0; Files.WriteBytes (out, N, 4)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
VAR
def : Def; obj : OCT.Object;
name, symbol : ARRAY 256 OF CHAR;
BEGIN (* OutHunkSymbol *)
IF OCM.Debug & ((codeHunk = InitCodeHunk) OR (codeHunk.defs # NIL))
THEN
blockType := hunkSymbol; Files.WriteBytes (out, blockType, 4);
IF codeHunk = InitCodeHunk THEN
COPY (OCT.ModuleName, symbol); Str.Append ("_INIT-CODE", symbol);
OutName (extSymb, symbol);
N := 0; Files.WriteBytes (out, N, 4);
END;
def := codeHunk.defs;
WHILE def # NIL DO
obj := def.object;
IF obj.mode = TProc THEN
COPY (OCT.ModuleName, symbol); Str.Append ("_", symbol);
OCT.GetName (obj.link.typ.strobj.name, name);
Str.Append (name, symbol); Str.Append ("_", symbol);
OCT.GetName (obj.name, name); Str.Append (name, symbol);
OutName (extSymb, symbol)
ELSIF obj.a0 = 0 THEN
OutName (extSymb, obj.label^)
ELSE
COPY (obj.label^, symbol); Str.Append ("_", symbol);
OCT.GetName (obj.name, name); Str.Append (name, symbol);
OutName (extSymb, symbol)
END;
Files.WriteBytes (out, def.offset, 4);
def := def.next
END;
N := 0; Files.WriteBytes (out, N, 4)
END;
END OutHunkSymbol;
BEGIN (* OutCodeHunk *)
OutHunkUnit (OCT.ModuleName);
IF OCM.SmallCode THEN OutHunkName (hunkSmallCode)
ELSE OutHunkName (OCT.ModuleName)
END;
OutHunkCode ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
END OutCodeHunk;
(*------------------------------------*)
PROCEDURE OutConstants ();
(*------------------------------------*)
PROCEDURE OutHunkData ();
VAR pos, len, pad : LONGINT;
BEGIN (* OutHunkData *)
IF OCM.Resident THEN blockType := hunkCode
ELSE blockType := hunkData
END;
Files.WriteBytes (out, blockType, 4);
N := (conx + 3) DIV 4;
Files.WriteBytes (out, N, 4);
pos := 0; len := conx;
WHILE pos < len DO
<*$ < NilChk- IndexChk- *>
Files.Write (out, constant [pos]);
<*$ > *>
INC (pos);
END; (* WHILE *)
pad := (((len + 3) DIV 4) * 4) - len;
WHILE pad > 0 DO
Files.Write (out, 0X);
DEC (pad);
END; (* WHILE *)
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
VAR ref : Ref;
BEGIN (* OutHunkExt *)
blockType := hunkExt;
Files.WriteBytes (out, blockType, 4);
OutDef0 (OCT.ConstLabel^, 0);
N := 0;
Files.WriteBytes (out, N, 4);
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
BEGIN (* OutHunkSymbol *)
IF OCM.Debug THEN
blockType := hunkSymbol;
Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.ConstLabel^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4);
END;
END OutHunkSymbol;
BEGIN (* OutConstants *)
IF conx > 0 THEN
OutHunkUnit (OCT.ModuleName);
IF OCM.SmallData THEN OutHunkName (hunkMerged)
ELSE OutHunkName (OCT.ModuleName)
END;
OutHunkData ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
END; (* IF *)
END OutConstants;
(*------------------------------------*)
PROCEDURE FindPtrs
( typ : OCT.Struct; adr : LONGINT; VAR offset : LONGINT );
VAR btyp : OCT.Struct; fld : OCT.Object; i, n, s : LONGINT;
BEGIN (* FindPtrs *)
IF
((typ.form = Pointer) & (typ.sysflg = OberonFlag))
OR (typ.form = PtrTyp)
THEN
Files.WriteBytes (out, adr, 4); DEC (offset, 4); INC (dataCount)
ELSIF (typ.form = Record) & (typ.sysflg = OberonFlag) THEN
btyp := typ.BaseTyp;
IF btyp # NIL THEN FindPtrs (btyp, adr, offset) END;
fld := typ.link;
WHILE fld # NIL DO
IF fld.mode = Fld THEN
IF fld.name < 0 THEN (* Hidden pointer field *)
n := fld.a0 + adr; Files.WriteBytes (out, n, 4);
DEC (offset, 4); INC (dataCount)
ELSE
FindPtrs (fld.typ, fld.a0 + adr, offset)
END
END;
fld := fld.left
END;
ELSIF typ.form = Array THEN
btyp := typ.BaseTyp; n := typ.n;
WHILE btyp.form = Array DO
n := btyp.n * n; btyp := btyp.BaseTyp
END;
IF (btyp.form IN {Pointer, PtrTyp, Record}) THEN
i := 0; s := btyp.size;
WHILE i < n DO
FindPtrs (btyp, i * s + adr, offset); INC (i)
END
END
END
END FindPtrs;
(*------------------------------------*)
PROCEDURE OutTypeDescs ();
VAR i : INTEGER; numProcs : LONGINT;
(*------------------------------------*)
PROCEDURE OutHunkData (typ : OCT.Struct);
VAR
pos1, pos2, N, i, nameLen : LONGINT;
name, objName : ARRAY 256 OF CHAR;
ch : CHAR;
BEGIN (* OutHunkData *)
IF OCM.Resident THEN blockType := hunkCode
ELSE blockType := hunkData
END;
Files.WriteBytes (out, blockType, 4);
pos1 := Files.Pos (out);
N := 0; Files.WriteBytes (out, N, 4);
numProcs := NumProcs (typ); INC (dataCount, numProcs);
i := numProcs;
WHILE i > 0 DO Files.WriteBytes (out, N, 4); DEC (i) END;
N := typ.size; Files.WriteBytes (out, N, 4);
i := 0; N := 0;
WHILE i < 16 DO Files.WriteBytes (out, N, 4); INC (i) END;
INC (dataCount, 17);
N := -68; FindPtrs (typ, 0, N); Files.WriteBytes (out, N, 4);
IF typ.strobj # NIL THEN
COPY (OCT.ModuleName, name); nameLen := SYS.STRLEN (name);
name [nameLen] := "."; INC (nameLen);
OCT.GetName (typ.strobj.name, objName);
i := 0;
REPEAT
ch := objName [i]; name [nameLen] := ch;
INC (i); INC (nameLen)
UNTIL ch = 0X
ELSE
name := ""; nameLen := 1
END;
FOR i := 0 TO nameLen - 1 DO
Files.Write (out, name [i]);
END;
WHILE (nameLen MOD 4) # 0 DO
Files.Write (out, 0X); INC (nameLen)
END;
INC (dataCount, nameLen DIV 4);
pos2 := Files.Pos (out);
Files.Set (out, ObjFile, pos1);
N := ((-N + nameLen) DIV 4) + numProcs + 1;
Files.WriteBytes (out, N, 4);
Files.Set (out, ObjFile, pos2);
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt (typ : OCT.Struct);
VAR N, i : LONGINT; lab : OCT.Label;
BEGIN (* OutHunkExt *)
N := hunkExt; Files.WriteBytes (out, N, 4);
i := numProcs;
WHILE i > 0 DO
lab := ProcLab (typ, i); OutName (extRef32, lab^);
N := 1; Files.WriteBytes (out, N, 4);
N := (numProcs - i) * 4; Files.WriteBytes (out, N, 4);
DEC (i)
END;
OutDef0 (typ.label^, numProcs * 4);
IF typ.form = Record THEN
WHILE (typ # NIL) & (typ.n >= 0) DO
OutName (extRef32, typ.label^);
N := 1; Files.WriteBytes (out, N, 4);
N := (numProcs + typ.n + 1) * 4; Files.WriteBytes (out, N, 4);
typ := typ.BaseTyp
END;
END;
N := 0; Files.WriteBytes (out, N, 4)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol (typ : OCT.Struct);
VAR N, i : LONGINT; name, symbol : ARRAY 256 OF CHAR;
BEGIN (* OutHunkSymbol *)
IF OCM.Debug THEN
N := hunkSymbol; Files.WriteBytes (out, N, 4);
IF (typ.form = Record) & (typ.strobj # NIL) THEN
COPY (OCT.ModuleName, symbol); Str.Append ("_", symbol);
OCT.GetName (typ.strobj.name, name); Str.Append (name, symbol);
OutName (extSymb, symbol)
ELSE
OutName (extSymb, typ.label^)
END;
N := numProcs * 4; Files.WriteBytes (out, N, 4);
N := 0; Files.WriteBytes (out, N, 4)
END;
END OutHunkSymbol;
BEGIN (* OutTypeDescs *)
dataCount := 0;
IF typex > 0 THEN
i := 0;
WHILE i < typex DO
OutHunkUnit (OCT.ModuleName);
IF OCM.SmallData THEN OutHunkName (hunkMerged)
ELSE OutHunkName (OCT.ModuleName)
END;
OutHunkData (type [i]);
OutHunkExt (type [i]);
OutHunkSymbol (type [i]);
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
INC (i)
END
END
END OutTypeDescs;
(*------------------------------------*)
PROCEDURE OutGC ();
VAR i : INTEGER;
(*------------------------------------*)
PROCEDURE OutHunkData ();
VAR i, N : LONGINT; obj : OCT.Object;
BEGIN (* OutHunkData *)
IF OCM.Resident THEN N := hunkCode
ELSE N := hunkData
END;
Files.WriteBytes (out, N, 4);
N := numPtrs + 1; Files.WriteBytes (out, N, 4);
obj := OCT.topScope.right;
WHILE obj # NIL DO
IF obj.mode = Var THEN FindPtrs (obj.typ, obj.a0, N) END;
obj := obj.link
END;
N := -1; Files.WriteBytes (out, N, 4);
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
VAR N : LONGINT;
BEGIN (* OutHunkExt *)
N := hunkExt; Files.WriteBytes (out, N, 4);
OutDef0 (OCT.GCLabel^, 0);
N := 0; Files.WriteBytes (out, N, 4)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
BEGIN (* OutHunkSymbol *)
IF OCM.Debug THEN
blockType := hunkSymbol; Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.GCLabel^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4)
END
END OutHunkSymbol;
BEGIN (* OutGC *)
IF numPtrs > 0 THEN
OutHunkUnit (OCT.ModuleName);
IF OCM.SmallData THEN OutHunkName (hunkMerged)
ELSE OutHunkName (OCT.ModuleName)
END;
OutHunkData ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd; Files.WriteBytes (out, blockType, 4)
END
END OutGC;
(*------------------------------------*)
PROCEDURE OutVars ();
BEGIN (* OutVars *)
OutHunkUnit (OCT.ModuleName);
IF (OCM.SmallData OR OCM.Resident) THEN OutHunkName (hunkMerged)
ELSE OutHunkName (OCT.ModuleName)
END;
blockType := hunkBSS;
Files.WriteBytes (out, blockType, 4);
N := (datasize + 3) DIV 4;
Files.WriteBytes (out, N, 4);
blockType := hunkExt;
Files.WriteBytes (out, blockType, 4);
OutDef0 (OCT.VarLabel^, 0);
N := 0; Files.WriteBytes (out, N, 4);
IF OCM.Debug THEN
blockType := hunkSymbol; Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.VarLabel^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4);
END;
blockType := hunkEnd; Files.WriteBytes (out, blockType, 4)
END OutVars;
<*$CopyArrays-*>
BEGIN (* OutCode *)
IF OCM.Force OR ~OCS.scanerr THEN
ObjFile := Files.New (FName);
IF ObjFile # NIL THEN
Files.Set (out, ObjFile, 0);
codeHunk := FirstCodeHunk;
WHILE codeHunk # NIL DO
OutCodeHunk (codeHunk);
codeHunk := codeHunk.next;
END; (* WHILE *)
OutConstants ();
OutTypeDescs ();
OutGC ();
OutVars ();
Files.Set (out, NIL, 0); Files.Register (ObjFile);
OCM.MakeIcon (FName, OCM.iconObj)
ELSE
OCS.Mark (153)
END
END;
END OutCode;
(*------------------------------------*)
PROCEDURE DataSize * () : LONGINT;
VAR size : LONGINT;
BEGIN (* DataSize *)
size := dataCount * 4 + conx;
RETURN size;
END DataSize;
BEGIN (* OCC *)
FirstCodeHunk := NIL; CurrCodeHunk := NIL; InitCodeHunk := NIL;
Prologue := NIL; NEW (wasderef);
FOR i := 0 TO (numKProcs - 1) DO NEW (kernelLab [i], 32) END;
COPY ("Kernel_Halt", kernelLab [kHalt]^);
COPY ("Kernel_NewRecord", kernelLab [kNewRecord]^);
COPY ("Kernel_NewArray", kernelLab [kNewArray]^);
COPY ("Kernel_NewSysBlk", kernelLab [kNewSysBlk]^);
COPY ("Kernel_Dispose", kernelLab [kDispose]^);
COPY ("Kernel_InitGC", kernelLab [kInitGC]^);
COPY ("Kernel_Move", kernelLab [kMove]^);
COPY ("Kernel_StackChk", kernelLab [kStackChk]^);
COPY ("Kernel_Mul32", kernelLab [kMul32]^);
COPY ("Kernel_Div32", kernelLab [kDiv32]^);
COPY ("Kernel_SPFix", kernelLab [kSPFix]^);
COPY ("Kernel_SPFlt", kernelLab [kSPFlt]^);
COPY ("Kernel_SPCmp", kernelLab [kSPCmp]^);
COPY ("Kernel_SPTst", kernelLab [kSPTst]^);
COPY ("Kernel_SPNeg", kernelLab [kSPNeg]^);
COPY ("Kernel_SPAdd", kernelLab [kSPAdd]^);
COPY ("Kernel_SPSub", kernelLab [kSPSub]^);
COPY ("Kernel_SPMul", kernelLab [kSPMul]^);
COPY ("Kernel_SPDiv", kernelLab [kSPDiv]^);
COPY ("Kernel_SPAbs", kernelLab [kSPAbs]^);
COPY ("Kernel_END", kernelLab [kEnd]^);
COPY ("Kernel_RegisterModule", kernelLab [kRegisterModule]^);
COPY ("Kernel_RegisterType", kernelLab [kRegisterType]^);
COPY ("Kernel_RegisterCommand", kernelLab [kRegisterCommand]^);
END OCC.
(*************************************************************************
$Log: OCC.mod $
Revision 5.23 1995/07/14 00:42:12 fjc
- Tried to make the genCode flag work, but failed :-(.
Revision 5.22 1995/06/15 18:12:19 fjc
- Changed register allocation to use A6 more.
Revision 5.21 1995/06/03 00:35:29 fjc
- Fixed incorrect error number.
Revision 5.20 1995/06/02 18:36:28 fjc
- Added genCode flag variable.
- Various changes to implementation of SMALLDATA and
RESIDENT options.
Revision 5.19 1995/05/19 16:01:52 fjc
- Uses OCOut for console IO.
Revision 5.18 1995/05/13 23:03:59 fjc
- Changes to allow code to be >32K.
Revision 5.17 1995/04/13 18:15:35 fjc
*** empty log message ***
Revision 5.16 1995/04/02 13:42:55 fjc
- Numerous changes to implement the small data model.
Revision 5.15 1995/03/23 18:07:23 fjc
- Fixes to register allocation and deallocation.
Revision 5.14 1995/03/13 11:24:55 fjc
- Changed register allocations procedures to allocate A6 as
a last resort.
- Added count field to RegState type and modified register
handling procedures to maintain it.
Revision 5.13 1995/03/09 19:07:23 fjc
- Incorporated changes from 5.22.
Revision 5.12 1995/02/27 16:57:34 fjc
- Removed tracing code.
- Implemented SMALLCODE option.
- Modified register handling code to remember which object
is loaded into a particular register.
Revision 5.11.1.2 1995/03/08 18:54:55 fjc
- OC 5.22
Revision 5.11.1.1 1995/02/27 19:11:17 fjc
- Fixed code buffer overflow bug.
Revision 5.11 1995/01/26 00:17:17 fjc
- Release 1.5
Revision 5.10 1995/01/09 13:54:08 fjc
- Added call to OCM.MakeIcon().
Revision 5.9 1995/01/05 11:32:29 fjc
- Changed to force output of object files if OCM.Force is TRUE.
Revision 5.8 1995/01/03 21:16:57 fjc
- Changed OCG to OCM.
Revision 5.7 1994/12/16 17:15:03 fjc
- Changed to accomodate renaming OCT.Symbol to OCT.Label.
- Added AllocSlots() to fix a serious bug that caused the
wrong slots to be allocated for type-bound procedures.
- Symbols output in object file are now different to the
corresponding linker labels in some cases.
Revision 5.6 1994/11/13 11:23:46 fjc
- Added kSPAbs.
Revision 5.5 1994/10/23 15:51:42 fjc
- Added kernelLab array and CallKernel().
- Fixed bug that made SYSTEM.PTR variables untraced.
Revision 5.4 1994/09/25 17:43:15 fjc
- Changed to reflect new object modes and system flags.
Revision 5.3 1994/09/15 10:24:29 fjc
- Replaced switches with pragmas.
Revision 5.2 1994/09/08 10:47:13 fjc
- Changed to use pragmas/options.
Revision 5.1 1994/09/03 19:29:08 fjc
- Bumped version number
*************************************************************************)